package com.q.tqb.util.http;

import android.content.Context;
import android.os.Handler;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.q.tqb.model.BaseInfo;
import com.q.tqb.util.LogUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


public class OkHttpUtil {

    private OkHttpClient client;
    private static OkHttpUtil instance;

    private OkHttpUtil() {
        client = new OkHttpClient().newBuilder()
                .addInterceptor(new LogInterceptor())
                .connectTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build();
    }


    public static OkHttpUtil getInstance() {
        if (instance == null) {
            instance = new OkHttpUtil();
        }
        return instance;
    }


    public void get(Context context, final String url, final IRawResponse responseHandler) {

        Request request = new Request.Builder()
                .url(url)
                .tag(context)
                .build();

        client.newCall(request).enqueue(new MyCallback1(new Handler(), responseHandler));
    }

    public void post(Context context, final String url, final Map<String, String> params, final IResponse responseHandler) {
        //post builder 参数
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }

        Request request;

        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .tag(context)
                    .build();
        }

        client.newCall(request).enqueue(new MyCallback(new Handler(), responseHandler));
    }

    public void post2(Context context, final String url, final Map<String, String> params, final IResponse2 responseHandler) {
        //post builder 参数
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }

        Request request;

        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .tag(context)
                    .build();
        }
        client.newCall(request).enqueue(new MyCallback3(new Handler(), responseHandler));
    }

    /**
     * 取消当前context的所有请求
     *
     * @param context
     */
    public void cancel(Context context) {
        if (client != null) {
            for (Call call : client.dispatcher().queuedCalls()) {
                if (call.request().tag().equals(context)) {
                    call.cancel();
                }
            }

            for (Call call : client.dispatcher().runningCalls()) {
                if (call.request().tag().equals(context)) {
                    call.cancel();
                }
            }

        }
    }


    private class MyCallback implements Callback {
        private Handler mHandler;
        private IResponse mResponse;


        public MyCallback(Handler handler, IResponse response) {
            mHandler = handler;
            mResponse = response;
        }

        @Override
        public void onFailure(Call call, final IOException e) {
            if (call.isCanceled()) {//关闭界面的取消请求执行这里
                LogUtil.i("已取消请求");
            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mResponse.onFailure(0, "网络错误，请检查您的网络!");
                    }
                });
            }
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            LogUtil.e("http", call.request().url().url().toString());
            baseResponse(response, mHandler, mResponse);
        }
    }

    private class MyCallback3 implements Callback {
        private Handler mHandler;
        private IResponse2 mResponse;


        public MyCallback3(Handler handler, IResponse2 response) {
            mHandler = handler;
            mResponse = response;
        }

        @Override
        public void onFailure(Call call, final IOException e) {
            if (call.isCanceled()) {//关闭界面的取消请求执行这里
                LogUtil.i("已取消请求");
            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mResponse.onFailure(0, "网络错误，请检查您的网络!");
                    }
                });
            }
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            LogUtil.e("http", call.request().url().url().toString());
            baseResponse2(response, mHandler, mResponse);
        }
    }

    private class MyCallback1 implements Callback {
        private Handler mHandler;
        private IRawResponse mResponseHandler;


        public MyCallback1(Handler handler, IRawResponse responseHandler) {
            mHandler = handler;
            mResponseHandler = responseHandler;
        }

        @Override
        public void onFailure(Call call, final IOException e) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mResponseHandler.onFailure("网络错误，请检查您的网络!");
                }
            });
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            rawResponse(response, mHandler, mResponseHandler);
        }
    }

    private void baseResponse(final Response response, Handler mHandler, final IResponse mResponseHandler) throws IOException {
        if (response.isSuccessful()) {
            final String responseBody = response.body().string();
            LogUtil.e("http", responseBody);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        Gson gson = new Gson();
                        BaseInfo baseInfo = gson.fromJson(responseBody, BaseInfo.class);
                        LogUtil.i(baseInfo.toString());
                        if (baseInfo.getCode() == 200) {
                            if (baseInfo.getData().isJsonPrimitive()) {
                                JsonElement jsonElement = gson.toJsonTree(baseInfo);
                                baseInfo.setData(jsonElement);
                            }
                            mResponseHandler.onSuccess(baseInfo.getData());
                        } else {
                            mResponseHandler.onFailure(baseInfo.getCode(), baseInfo.getMsg());
                        }
                    } catch (Exception e) {
                        LogUtil.i("数据处理报错" + responseBody + e.toString());
                        mResponseHandler.onFailure(response.code(), "网络错误，请检查您的网络！");
                    }

                }
            });
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    LogUtil.e("fail status=" + response.code());
                    mResponseHandler.onFailure(0, "网络错误，请检查您的网络！");
                }
            });
        }
    }

    private void baseResponse2(final Response response, Handler mHandler, final IResponse2 mResponseHandler) throws IOException {
        if (response.isSuccessful()) {
            final String responseBody = response.body().string();
            LogUtil.e("http", responseBody);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        Gson gson = new Gson();
                        BaseInfo baseInfo = gson.fromJson(responseBody, BaseInfo.class);
                        LogUtil.i(baseInfo.toString());
                        if (baseInfo.getCode() == 200) {
                            if (baseInfo.getData().isJsonPrimitive()) {
                                JsonElement jsonElement = gson.toJsonTree(baseInfo);
                                baseInfo.setData(jsonElement);
                            }
                            mResponseHandler.onSuccess(baseInfo.getData(), baseInfo.getMsg());
                        } else {
                            mResponseHandler.onFailure(baseInfo.getCode(), baseInfo.getMsg());
                        }
                    } catch (Exception e) {
                        LogUtil.i("数据处理报错" + responseBody + e.toString());
                        mResponseHandler.onFailure(response.code(), "网络错误，请检查您的网络！");
                    }

                }
            });
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    LogUtil.e("fail status=" + response.code());
                    mResponseHandler.onFailure(0, "网络错误，请检查您的网络！");
                }
            });
        }
    }

    private void rawResponse(final Response response, Handler mHandler, final IRawResponse rawResponseHandler) throws IOException {
        if (response.isSuccessful()) {
            final String responseBody = response.body().string();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    rawResponseHandler.onSuccess(responseBody);
                }
            });
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    rawResponseHandler.onFailure("网络错误，请检查您的网络！");
                }
            });
        }
    }

}

